import type { ComponentStyleIdType } from '../../types/interfaces'
import type { SortOption, SortOrderType, SortProps } from './types'
import { UIComponent } from '../../lib/abstract'
import { ICON_IDS } from '../../lib/icons/types/constants'
import { ComponentStyleId } from '../../types/constants'
import { ThemeType } from '../../types/interfaces'
import { styles } from './styles'
import { DEFAULT_SORT_PROPS } from './types'

export class SortOrder extends UIComponent<SortProps> {
  id: string = 'sort-order'
  private isOpen = false
  readonly styleId: string = ComponentStyleId[this.name]

  get name(): ComponentStyleIdType {
    return 'SortOrder'
  }

  get className(): string {
    return 'custom-sort'
  }

  constructor(props: SortProps) {
    super({
      ...DEFAULT_SORT_PROPS,
      ...props,
    })

    // 注册样式
    this.registerStyles()
  }

  ELEMENT_SELECTORS = {
    sortOrder: { selector: `.sort-order`, dynamic: false, unique: false },
    arrow: { selector: `.sort-arrow`, dynamic: false, unique: false },
    up: { selector: `.sort-arrow.up`, dynamic: false, unique: false },
    down: { selector: `.sort-arrow.down`, dynamic: false, unique: false },
    currentType: { selector: `.current-type`, dynamic: false, unique: false },
    optionsDropdown: { selector: `.options-dropdown`, dynamic: false, unique: false },
    option: { selector: `.options-dropdown .option`, dynamic: false, unique: false },
  }

  render(): string {
    const { order, type, options, theme = ThemeType.LIGHT } = this.props
    const currentOption = options.find((opt: { value: any }) => opt.value === type) || options[0]

    return `
      <div class="${this.className}">
        <div class="sort-order">
          <div class="sort-arrow up ${order === 'asc' ? 'active' : ''}" data-type="up">
            ${this.iconService.api.icon.asSvg(ICON_IDS.navigation.arrowsUp, { size: 12, theme })}
          </div>
          <div class="sort-arrow down ${order === 'desc' ? 'active' : ''}" data-type="down">
            ${this.iconService.api.icon.asSvg(ICON_IDS.navigation.arrowsDown, { size: 12, theme })}
          </div>
        </div>
        <div class="sort-selector">
          <div class="current-type">${currentOption.label}</div>
          <div class="options-dropdown ${this.isOpen ? 'open' : ''}">
            ${options.map((opt: SortOption) => `
              <div class="option ${opt.value === type ? 'active' : ''}" data-value="${opt.value}">${opt.label}</div>
            `).join('')}
          </div>
        </div>
      </div>
    `
  }

  bindEvents(): void {
    const $option = this.getElement('option')

    this.getElement('up')?.on('click', (e) => {
      const $element = $(e.currentTarget)
      this.setArrow($element)
      this.props.onChange(this.getCurrentType(), 'asc')
    })

    this.getElement('down')?.on('click', (e) => {
      const $element = $(e.currentTarget)
      this.setArrow($element)
      this.props.onChange(this.getCurrentType(), 'desc')
    })

    this.getElement('currentType')?.on('click', () => {
      this.handleOptionsDropdown()
    })

    $option?.on('click', (e) => {
      const $element = $(e.currentTarget)
      const type = $element.data('value')

      this.setOption($element)

      this.props.onChange(type, this.getCurrentOrder())
      this.closeOptionsDropdown()
    })

    // 点击外部关闭
    $(document).on('click.sortOrder', (e) => {
      if (!this.$element?.get(0)?.contains(e.target)) {
        this.closeOptionsDropdown()
      }
    })
  }

  /**
   * 处理排序选项下拉框
   */
  private handleOptionsDropdown(): void {
    this.isOpen = !this.isOpen
    this.getElement('optionsDropdown')?.toggleClass('open', this.isOpen)
  }

  /**
   * 关闭排序选项下拉框
   */
  private closeOptionsDropdown(): void {
    this.isOpen = false
    this.getElement('optionsDropdown')?.removeClass('open')
  }

  private getCurrentType(): string {
    return this.getElement('optionsDropdown')?.find('.option.active').data('value') || DEFAULT_SORT_PROPS.type
  }

  private getCurrentOrder(): SortOrderType {
    return this.getElement('sortOrder')?.find('.active').data('type') || 'asc'
  }

  private setOption($element: JQuery<HTMLElement>): void {
    this.getElement('option')?.removeClass('active')
    $element.addClass('active')
    this.getElement('currentType')?.text($element.text())
  }

  private setArrow($element: JQuery<HTMLElement>): void {
    this.closeOptionsDropdown()
    this.getElement('arrow')?.removeClass('active')
    $element.addClass('active')
  }

  getStyles(): string {
    return styles(this.className)
  }

  destroy(): void {
    super.destroy()
  }
}
